﻿using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using Commons.Xml.Relaxng;

namespace XmlRuleBuilder
{
    public static class ATOMValidator
    {
        public static void Validate(XmlNode node, string mdXml, Macro macro)
        {
            // Input files
            string ruleRNG = "Schema.rng";
            string instanceXml = "Sample.xml";

            bool isXSLTTransformSuccess = true;
            XmlTextWriter myWriter = new XmlTextWriter(ruleRNG, null);

            // Transform the XSL stylesheet
            if (node.Attributes["processor"].Value == "xslt+rng")
            {
                try
                {
                    // Load the Metadata file
                    XPathDocument myXPathDoc = new XPathDocument(mdXml);

                    // Repalce the macros                       
                    string temp = Helper.MacroReplacement(node.InnerXml, macro);

                    // Load the XSL from the node
                    XslCompiledTransform myXslTrans = new XslCompiledTransform(true);
                    XmlReader reader = XmlReader.Create(new StringReader(temp));
                    reader.ReadToDescendant("xsl:stylesheet");
                    myXslTrans.Load(reader);

                    // Write to Schema.rng
                    myXslTrans.Transform(myXPathDoc, null, myWriter);
                    myWriter.Close();
                }
                catch (Exception ex)
                {
                    isXSLTTransformSuccess = false;
                    Console.WriteLine("XSLT Transform failed. Exception: {0}", ex.Message);
                }
            }
            else
            {
                myWriter.WriteRaw(node.InnerXml);
                myWriter.Close();
            }

            if (isXSLTTransformSuccess)
            {

                //Validate the RNG Schema grammar            
                XmlTextReader xtrRNG = new XmlTextReader(ruleRNG);
                RelaxngPattern rngPattern = null;
                bool isSchemaValid = false;

                try
                {
                    rngPattern = RelaxngPattern.Read(xtrRNG);
                    rngPattern.Compile();
                    isSchemaValid = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(string.Format("Malformed RNG Schema : {0}", ex.Message));
                }
                finally
                {
                    xtrRNG.Close();
                }

                if (isSchemaValid)
                {
                    // Validate instance xml against the RNG Schema
                    XmlTextReader xtrXml = new XmlTextReader(instanceXml);
                    RelaxngValidatingReader rngValidatingReader = new RelaxngValidatingReader(xtrXml, rngPattern);

                    try
                    {
                        while (!rngValidatingReader.EOF)
                        {
                            rngValidatingReader.Read();
                        }

                        Console.WriteLine("XML Instance is valid!");
                    }
                    catch (RelaxngException ex)
                    {
                        Console.WriteLine(string.Format("XML instance is invalid : {0}", ex.Message));
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(string.Format("Malformed XML instance : {0}", ex.Message));
                    }
                    finally
                    {
                        rngValidatingReader.Close();
                        xtrXml.Close();
                    }
                }
            }
        }
    }
}